<?php

namespace App\JsonRPC;

use Throwable;

class Response
{
    protected string $jsonrpc = '2.0';

    /**
     * @return string
     */
    public function getJsonrpc(): string
    {
        return $this->jsonrpc;
    }

    /**
     * @param string $jsonrpc
     */
    public function setJsonrpc(string $jsonrpc): void
    {
        $this->jsonrpc = $jsonrpc;
    }

    protected string $id;

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @param string $id
     */
    public function setId(string $id): void
    {
        $this->id = $id;
    }

    protected array $result;

    /**
     * @return array
     */
    public function getResult(): array
    {
        return $this->result;
    }

    /**
     * @param array $result
     */
    public function setResult(array $result): void
    {
        $this->result = $result;
    }

    protected array $error = [];

    /**
     * @return array
     */
    public function getError(): array
    {
        return $this->error;
    }

    /**
     * @param array $error
     */
    public function setError(array $error): void
    {
        $this->error = $error;
    }

    public function toArray(): array
    {
        $arr = [
            'jsonrpc' => $this->getJsonrpc(),
            'id' => $this->getId(),
        ];
        if (!empty($this->getError())) {
            $arr['error'] = $this->getError();
        } else {
            $arr['result'] = $this->getResult();
        }
        return $arr;
    }

    public static function createFromResult(Procedure $procedure, array $result)
    {
        $response = new self;
        $response->setJsonrpc($procedure->getRequestContext()->getJsonrpc());
        $response->setId($procedure->getRequestContext()->getId());
        $response->setResult($result);
        return $response;
    }

    public static function createFromError(Procedure $procedure, Error $error)
    {
        $response = new self;
        $response->setJsonrpc($procedure->getRequestContext()->getJsonrpc());
        $response->setId($procedure->getRequestContext()->getId());
        $response->setError([
            'code' => $error->getCode(),
            'message' => $error->getMessage(),
        ]);
        return $response;
    }

    public static function createFromException(Procedure $procedure, Throwable $exception)
    {
        $response = new self;
        $response->setJsonrpc($procedure->getRequestContext()->getJsonrpc());
        $response->setId($procedure->getRequestContext()->getId());
        $response->setError([
            'code' => $exception->getCode(),
            'message' => $exception->getMessage(),
        ]);
        return $response;
    }
}
